package com.ocm.tourism.picasaweb.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ocm.tourism.core.exception.TourismRuntimeException;
import com.ocm.tourism.core.model.ImageItem;
import com.ocm.tourism.core.util.TourismUtil;

@Service("imageUploader")
public class ImageUploaderServiceImpl implements ImageUploaderService {

   @Autowired
   private GoogleAuthenticationService googleAuthenticationService;

   @Override
   public List<ImageItem> retriveFiles(String albumId) {
      String albumLocation = getFilesUri(albumId);
      HttpClient client = new DefaultHttpClient();
      HttpGet get = new HttpGet(albumLocation);
      try {
         String auth = googleAuthenticationService.getAuthenticationString();
         get.addHeader("Authorization", "GoogleLogin auth=" + auth);
         get.addHeader("GData-Version", "2");
         get.addHeader("Content-Type", "application/atom+xml");
         HttpResponse response = client.execute(get);
         StatusLine line = response.getStatusLine();
         if (line.getStatusCode() > 201) {
            throw new Exception("Fail Retreive files");
         }
         HttpEntity entity = response.getEntity();
         if (entity != null) {
            InputStream is = entity.getContent();
            String str = TourismUtil.convert(is);
            List<ImageItem> imageItems = processFromAlbum(str);
            return imageItems;
        }
      }catch (Exception e) {
         get.abort();
         client.getConnectionManager().shutdown();
         throw new TourismRuntimeException(e.getMessage());
      }
      return null;
   }

   public String upload(String albumId, ImageItem imageItem) {
      // create items for http client
      //albumLocation = "http://picasaweb.google.com/data/feed/api/user/dulichtayninh2/albumid/5811448820683929521";
      String albumLocation = getUploadFileUri(albumId);
      HttpClient client = new DefaultHttpClient();
      HttpPost post = new HttpPost(albumLocation);

      try {
         // new file and and entity
         Multipart multipart = new Multipart("Media multipart posting", "END_OF_PART");

         // create entity parts
         multipart
               .addPart(
                     "<entry xmlns='http://www.w3.org/2005/Atom'><title>"
                           + imageItem.getTitle()
                           + "</title><category scheme=\"http://schemas.google.com/g/2005#kind\" term=\"http://schemas.google.com/photos/2007#photo\"/></entry>",
                     "application/atom+xml");
         multipart.addPart(imageItem.getBytes(), imageItem.getFileType());

         // create new Multipart entity
         MultipartEntity entity = new MultipartEntity(multipart);

         // get http params
         HttpParams params = client.getParams();

         // set protocal and timeout for httpclient
         params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
         params.setParameter(CoreConnectionPNames.SO_TIMEOUT, new Integer(15000));
         params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, new Integer(15000));

         // set body with upload entity
         post.setEntity(entity);

         // set headers
         String auth = googleAuthenticationService.getAuthenticationString();
         post.addHeader("Authorization", "GoogleLogin auth=" + auth);
         post.addHeader("GData-Version", "2");
         post.addHeader("MIME-version", "1.0");
         post.addHeader("Content-Type", "multipart/related;boundary=END_OF_PART");

         // execute upload to picasa and get response and status
         HttpResponse response = client.execute(post);
         StatusLine line = response.getStatusLine();

         // return code indicates upload failed so throw exception
         if (line.getStatusCode() > 201) {
            throw new Exception("Failed upload");
         }

         String contentLocation = response.getFirstHeader("Content-Location").getValue();

         // shut down connection
         client.getConnectionManager().shutdown();

         return contentLocation;
      } catch (Exception e) {
         // file upload failed so abort post and close connection
         post.abort();
         client.getConnectionManager().shutdown();
         throw new TourismRuntimeException(e.getMessage());
      }
   }

   @Override
   public boolean deleteFile(String albumId, String fileId) {
      String fileLocation = getDeleteFilesUri(albumId, fileId);
      HttpClient client = new DefaultHttpClient();
      HttpDelete delete = new HttpDelete(fileLocation);

      try {
         // set headers
         String auth = googleAuthenticationService.getAuthenticationString();
         delete.addHeader("Authorization", "GoogleLogin auth=" + auth);
         delete.addHeader("GData-Version", "2");
         delete.addHeader("If-Match", "*");

         // execute upload to picasa and get response and status
         HttpResponse response = client.execute(delete);
         StatusLine line = response.getStatusLine();

         // return code indicates upload failed so throw exception
         if (line.getStatusCode() > 201) {
            throw new Exception("Failed delete file");
         }

         // shut down connection
         client.getConnectionManager().shutdown();

      } catch (Exception e) {
         // file upload failed so abort post and close connection
         delete.abort();
         client.getConnectionManager().shutdown();
         throw new TourismRuntimeException(e.getMessage());
      }
      return true;
   }

   @Override
   public String createAlbum(String albumName) {
      // create items for http client
      String url = "http://picasaweb.google.com/data/feed/api/user/dulichtayninh2";
      HttpClient client = new DefaultHttpClient();
      HttpPost post = new HttpPost(url);

      try {
         String entry = "<entry xmlns='http://www.w3.org/2005/Atom'><title>"
               + albumName
               + "</title><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'/></entry>";
         StringEntity entity = new StringEntity(entry);

         // get http params
         HttpParams params = client.getParams();

         // set protocal and timeout for httpclient
         params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
         params.setParameter(CoreConnectionPNames.SO_TIMEOUT, new Integer(15000));
         params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, new Integer(15000));

         // set body with upload entity
         post.setEntity(entity);

         // set headers
         String auth = googleAuthenticationService.getAuthenticationString();
         post.addHeader("Authorization", "GoogleLogin auth=" + auth);
         post.addHeader("GData-Version", "2");
         post.addHeader("Content-Type", "application/atom+xml");

         // execute upload to picasa and get response and status
         HttpResponse response = client.execute(post);
         StatusLine line = response.getStatusLine();

         // return code indicates upload failed so throw exception
         if (line.getStatusCode() > 201) {
            throw new Exception("Failed create Album");
         }

         String contentLocation = response.getFirstHeader("Content-Location").getValue();
         String albumId = processAlbumId(contentLocation);
         // shut down connection
         client.getConnectionManager().shutdown();

         return albumId;
      } catch (Exception e) {
         // file upload failed so abort post and close connection
         post.abort();
         client.getConnectionManager().shutdown();
         throw new TourismRuntimeException(e.getMessage());
      }
   }

   public int totalFiles(String albumId) {
      String albumLocation = getAlbumInfo(albumId, "fields=gphoto:numphotos");
      HttpClient client = new DefaultHttpClient();
      HttpGet get = new HttpGet(albumLocation);
      try {
         String auth = googleAuthenticationService.getAuthenticationString();
         get.addHeader("Authorization", "GoogleLogin auth=" + auth);
         get.addHeader("GData-Version", "2");
         get.addHeader("Content-Type", "application/atom+xml");
         HttpResponse response = client.execute(get);
         StatusLine line = response.getStatusLine();
         if (line.getStatusCode() > 201) {
            throw new Exception("Fail Retreive files");
         }
         HttpEntity entity = response.getEntity();
         if (entity != null) {

            InputStream is = entity.getContent();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String str ="";
            StringBuffer content = new StringBuffer();
            while ((str = br.readLine()) != null){
               content.append(str);
            }
            int numberPhotos = processNumberPhotos(content.toString());
            return numberPhotos;
        }
      }catch (Exception e) {
         get.abort();
         client.getConnectionManager().shutdown();
         throw new TourismRuntimeException(e.getMessage());
      }
      return 0;
   }

   private String getUploadFileUri(String albumId){
       String uri = "http://picasaweb.google.com/data/feed/api/user/dulichtayninh2/albumid/" + albumId;
       return uri;
   }

   private String getFilesUri(String albumId){
      String uri = "http://picasaweb.google.com/data/feed/api/user/dulichtayninh2/albumid/" + albumId;
      uri += "?fields=entry/gphoto:id,entry/media:group/media:content,entry/media:group/media:thumbnail,entry/media:group/media:title";
      return uri;
   }

   private String getDeleteFilesUri(String albumId, String photoId){
      String uri = "http://picasaweb.google.com/data/entry/api/user/dulichtayninh2/albumid/"+albumId+"/photoid/"+photoId;
      return uri;
   }

   private String getAlbumInfo(String albumId, String filter){
      String uri = "http://picasaweb.google.com/data/entry/api/user/dulichtayninh2/albumid/"+ albumId;
      if (filter != null)
         uri += "?" + filter;
      return uri;
   }

   public int processNumberPhotos(String content){
      String strDelim = "<gphoto:numphotos>";
      int indexOf = content.lastIndexOf(strDelim);
      int lastIndeOf = content.indexOf("</gphoto:numphotos>");
      String number = content.substring(indexOf + strDelim.length(), lastIndeOf);
      return Integer.parseInt(number);
   }
   
   public String processAlbumId(String contentLocation){
      int indexOf = contentLocation.lastIndexOf("/");
      int lastIndeOf = contentLocation.indexOf("?");
      String id = contentLocation.substring(indexOf + 1, lastIndeOf);
      return id;
   }

   private List<ImageItem> processFromAlbum(String content){
      List<ImageItem> imageItems = new ArrayList<ImageItem>();
      String processContent = content;
      boolean hasExist = true;
      while (hasExist){
         int entryIndex = processContent.indexOf("<entry>");
         if (entryIndex < 0 ){
            break;
         }
         int closedEntryIndex = processContent.indexOf("</entry>"); 
         String entryElement  = processContent.substring(0, closedEntryIndex);
         ImageItem imageItem = processImageItem(entryElement);
         imageItems.add(imageItem);
         processContent = processContent.substring("</entry>".length() + closedEntryIndex);
      }
      return imageItems;
   }

   private ImageItem processImageItem(String entryElement){
      ImageItem imageItem = new ImageItem();

      String strDelim = "<gphoto:id>";
      String strCloseDelim = "</gphoto:id>";
      int indexOf = entryElement.indexOf(strDelim);
      String strProcessing = entryElement.substring(indexOf + strDelim.length());
      int lastIndeOf = strProcessing.indexOf(strCloseDelim);
      String externalId = strProcessing.substring(0, lastIndeOf);
      strProcessing = strProcessing.substring(lastIndeOf + strCloseDelim.length());

      strDelim = "<media:content ";
      indexOf = strProcessing.indexOf(strDelim);
      strProcessing = strProcessing.substring(indexOf + strDelim.length());
      indexOf = strProcessing.indexOf("/>");
      String nextString = strProcessing.substring(0, indexOf);
      indexOf = nextString.indexOf("'");
      String urlContent = nextString.substring(indexOf + 1);
      lastIndeOf = urlContent.indexOf("'");
      String contentUrl = urlContent.substring(0, lastIndeOf);

      strDelim = "<media:thumbnail ";
      indexOf = strProcessing.indexOf(strDelim);
      strProcessing = strProcessing.substring(indexOf + strDelim.length());
      lastIndeOf = strProcessing.indexOf("/><media:thumbnail");
      String nextThumbnailElement = strProcessing.substring(0, lastIndeOf);
      indexOf = nextThumbnailElement.indexOf("'");
      urlContent = nextThumbnailElement.substring(indexOf + 1);
      lastIndeOf = urlContent.indexOf("'");
      String url = urlContent.substring(0, lastIndeOf);

      strDelim = "<media:title type='plain'>";
      indexOf = strProcessing.indexOf(strDelim);
      lastIndeOf = strProcessing.indexOf("</media:title>");
      String fileName = strProcessing.substring(indexOf + strDelim.length(), lastIndeOf);

      imageItem.setFileName(fileName);
      imageItem.setTitle(fileName);
      imageItem.setContentLocation(url);
      imageItem.setExternalId(externalId);
      imageItem.setRealContentLocation(contentUrl);
      return imageItem;
   }

   public static void main(String[] args) throws IOException {
      
        /*ImageItem imageItem = new ImageItem();
        imageItem.setFileName("Test Uploader");
        imageItem.setFileType("image/jpeg");
        imageItem.setTitle("Test Uploader"); 
        File file = new  File("D:/IMG_0828.JPG"); 
        InputStream is = new FileInputStream(file);
        byte[] bytes = new byte[(int) file.length()]; 
        int offset = 0; 
        int numRead = 0;
        
        // reaf file into byte array 
        while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { 
           offset +=  numRead; 
        }
        
        // errror checking 
        if (offset < bytes.length){ 
           throw new IOException("Could not completely read file " + file.getName()); 
        }
        
        // close input stream 
        is.close(); 
        imageItem.setBytes(bytes);*/
       
      ImageUploaderServiceImpl imageUploaderServiceImpl = new ImageUploaderServiceImpl();
      //imageUploaderServiceImpl.upload("",imageItem);
      //imageUploaderServiceImpl.createAlbum("Test Create Ablum");
      //System.out.println(imageUploaderServiceImpl.processAlbumId("http://picasaweb.google.com/data/feed/api/user/dulichtayninh2/albumid/5811448820683929521?authe=dhsfdjshfjds"));
      imageUploaderServiceImpl.retriveFiles("5815767656781966369");
   }
}
